package cn.b.sky.mes.mm.service.impl;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import cn.b.sky.mes.mm.constants.MmConstant;
import cn.b.sky.mes.mm.dao.InventoryDao;
import cn.b.sky.mes.mm.dao.SafetyinventroyDao;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import cn.b.sky.mes.cm.model.Material;
import cn.b.sky.mes.cm.model.WorkCenter;
import cn.b.sky.mes.cm.model.WorkUnit;
import cn.b.sky.mes.cm.service.MaterialService;
import cn.b.sky.mes.cm.service.WorkCenterService;
import cn.b.sky.mes.cm.service.WorkUnitService;
import cn.b.sky.mes.mm.model.Inventory;
import cn.b.sky.mes.mm.model.InventoryItem;
import cn.b.sky.mes.mm.model.InventoryMove;
import cn.b.sky.mes.mm.model.MoveType;
import cn.b.sky.mes.mm.model.PFEP;
import cn.b.sky.mes.mm.model.Requirement;
import cn.b.sky.mes.mm.model.Safetyinventroy;
import cn.b.sky.mes.mm.model.Warehouse;
import cn.b.sky.mes.mm.service.InventoryAlarmRecipientService;
import cn.b.sky.mes.mm.service.InventoryService;
import cn.b.sky.mes.mm.service.PFEPService;
import cn.b.sky.mes.mm.service.WarehouseService;
import cn.b.sky.common.exception.ImeException;
import cn.b.sky.user.SecurityContextUtil;

/**
 * 
 * <strong>Title : InventoryServiceImpl.java<br>
 * </strong> <strong>Package : cn.b.sky.mes.mm.service.impl<br>
 * </strong> <strong>Description : </strong>库存操作业务实现类<br>
 * <strong>Create on : 2016-3-3 下午07:52:44<br>
 * </strong>
 * <p>
 * 
 * @author zhaoxin01<br>
 * @version <strong>v1.0.0</strong><br>
 * <br>
 *          <strong>修改历史:</strong><br>
 *          修改人 | 修改日期 | 修改描述<br>
 *          -------------------------------------------<br>
 * <br>
 * <br>
 */
@Service("inventoryService")
public class InventoryServiceImpl implements InventoryService {
  @Resource
  InventoryDao inventoryDao;

  @Resource
  WarehouseService warehouseService;

  @Resource
  SafetyinventroyDao safetyinventroyDao;

  @Resource
  InventoryAlarmRecipientService inventoryAlarmRecipientService;

  @Resource
  MaterialService materialService;

  @Resource
  WorkUnitService workUnitService;

  @Resource
  WorkCenterService workCenterService;

  @Resource
  PFEPService pFEPService;

  @Override
  public List<Warehouse> selectUserWarehouseList(String siteCode, String userCode, String moveDirectionECode) {
    return inventoryDao.selectUserWarehouseList(siteCode, userCode, moveDirectionECode);
  }

  @Override
  public List<MoveType> selectMoveTypeByDirection(String siteCode, String userCode, String warehouseCode,
                                                  String moveDirectionECode) {
    return inventoryDao.selectMoveTypeByDirection(siteCode, userCode, warehouseCode, moveDirectionECode);
  }

  @Override
  public void insertInventoryMove(InventoryMove inventoryMove) {
    inventoryDao.insertInventoryMove(inventoryMove);

  }

  @Override
  public void insertInventory(Inventory inventory) {
    inventoryDao.insertInventory(inventory);

  }

  @Override
  public void updateInventory(Inventory inventory) {
    inventoryDao.updateInventory(inventory);

  }

  @Override
  public Inventory selectInventory(String siteCode, String materialCode, String warehouseCode) {
    return inventoryDao.selectInventory(siteCode, materialCode, warehouseCode);
  }

  @Override
  public void deleteInventory(String siteCode, String materialCode, String warehouseCode) {
    inventoryDao.deleteInventory(siteCode, materialCode, warehouseCode);

  }

  @Override
  public void insertInventoryItem(InventoryItem inventoryItem) {
    inventoryDao.insertInventoryItem(inventoryItem);

  }

  @Override
  public void updateInventoryItem(InventoryItem inventoryItem) {
    inventoryDao.updateInventoryItem(inventoryItem);

  }

  @Override
  public InventoryItem selectInventoryItem(InventoryItem inventoryItem) {
    return inventoryDao.selectInventoryItem(inventoryItem);
  }

  @Override
  public void deleteInventoryItem(long id) {
    inventoryDao.deleteInventoryItem(id);

  }

  @Override
  public void doOutStock(InventoryMove inventoryMove) {
    InventoryItem item = new InventoryItem();
    item.setSiteCode(inventoryMove.getSiteCode());
    item.setMaterialCode(inventoryMove.getMaterialCode());
    item.setWarehouseCode(inventoryMove.getFromWarehouseCode());
    item.setSupplierCode(inventoryMove.getSupplierCode());
    item.setLotNum(inventoryMove.getLotNum());
    item.setStorageLocationCode(inventoryMove.getFromLocationCode());
    InventoryItem inventoryItem = inventoryDao.selectInventoryItem(item);
    if (inventoryItem != null) {
      outStock(inventoryMove, inventoryItem);
    } else {
      throw ImeException.newException("canNotOut.M");
    }

  }

  private void outStock(InventoryMove inventoryMove, InventoryItem inventoryItem) {
    Warehouse warehouse = warehouseService.getWarehouse(inventoryMove.getFromWarehouseCode(),
        inventoryMove.getSiteCode());
    boolean canNegative = warehouse.getNegativeInventoryFlag().intValue() == 1 ? true : false;
    if (inventoryItem.getQuantity().doubleValue() < inventoryMove.getQuantity().doubleValue() && !canNegative) {
      throw ImeException.newException("outQtyError.M");
    } else {
      boolean isLocationSafetyInventroy = false;
      Material material = materialService.selectMaterial(inventoryMove.getSiteCode(), inventoryMove.getMaterialCode());
      // 新增移动记录
      inventoryDao.insertInventoryMove(inventoryMove);
      Safetyinventroy safetyinventroy = null;
      if (warehouse.getLocationManageFlag() == 1) {
        safetyinventroy = safetyinventroyDao.selectSafetyinventroy(inventoryMove.getSiteCode(),
            inventoryMove.getMaterialCode(), inventoryMove.getFromWarehouseCode(), inventoryMove.getFromLocationCode());
        if (safetyinventroy != null) {
          isLocationSafetyInventroy = true;
          if (inventoryItem.getQuantity() - inventoryMove.getQuantity() < safetyinventroy.getSafetyInventory()) {
            // 低于安全库存需要报警
            inventoryAlarmRecipientService.doSendAlarm(inventoryMove.getSiteCode(),
                inventoryMove.getFromLocationCode(), inventoryMove.getFromWarehouseCode(),
                material.getMaterialTypeCode(), inventoryMove.getMaterialCode(), isLocationSafetyInventroy);
          }
        }
      }
      if (inventoryItem.getQuantity().doubleValue() == inventoryMove.getQuantity().doubleValue()) {
        // 出库后库位明细为0时，删除库存明细
        inventoryDao.deleteInventoryItem(inventoryItem.getId());
      } else {
        // 更新库存明细数量
        inventoryItem.setQuantity(inventoryItem.getQuantity() - inventoryMove.getQuantity());
        inventoryItem.setModifyUser(inventoryMove.getCreateUser());
        inventoryItem.setModifyDateTime(new Date());
        inventoryDao.updateInventoryItem(inventoryItem);
      }
      Inventory inventory = inventoryDao.selectInventory(inventoryMove.getSiteCode(), inventoryMove.getMaterialCode(),
          inventoryMove.getFromWarehouseCode());
      if (!isLocationSafetyInventroy) {
        safetyinventroy = safetyinventroyDao.selectSafetyinventroy(inventoryMove.getSiteCode(),
            inventoryMove.getMaterialCode(), inventoryMove.getFromWarehouseCode(), null);
        if (safetyinventroy != null) {
          isLocationSafetyInventroy = false;
          if (inventory.getQuantity() - inventoryMove.getQuantity() < safetyinventroy.getSafetyInventory()) {
            // 低于安全库存需要报警
            inventoryAlarmRecipientService.doSendAlarm(inventoryMove.getSiteCode(),
                inventoryMove.getFromLocationCode(), inventoryMove.getFromWarehouseCode(),
                material.getMaterialTypeCode(), inventoryMove.getMaterialCode(), isLocationSafetyInventroy);
          }
        }
      }
      if (inventory.getQuantity().doubleValue() == inventoryMove.getQuantity().doubleValue()) {
        // 出库后库位为0时，删除库存
        inventoryDao
            .deleteInventory(inventory.getSiteCode(), inventory.getMaterialCode(), inventory.getWarehouseCode());
      } else {
        // 更新库存数量
        inventory.setQuantity(inventory.getQuantity() - inventoryMove.getQuantity());
        inventory.setModifyUser(inventoryMove.getCreateUser());
        inventory.setModifyDateTime(new Date());
        inventoryDao.updateInventory(inventory);
      }

    }
  }

  @Override
  public void doInStock(InventoryMove inventoryMove) {
    doInStockOnly(inventoryMove);
    // 新增入库记录
    inventoryDao.insertInventoryMove(inventoryMove);
  }

  @Override
  public void doMoveStock(InventoryMove inventoryMove) {
    doOutStock(inventoryMove);
    doInStockOnly(inventoryMove);
  }

  /**
   * 
   * <strong>Title : doInStockOnly<br>
   * </strong> <strong>Description : </strong>仅入库，不保存记录<br>
   * <strong>Create on : 2016年3月7日 下午5:18:08<br>
   * </strong>
   * <p>
   * 
   * @param inventoryMove
   *            void
   * @throws
   * @author dapeng.li<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   *          <strong>修改历史:</strong><br>
   *          修改人 | 修改日期 | 修改描述<br>
   *          -------------------------------------------<br>
   * <br>
   * <br>
   */
  private void doInStockOnly(InventoryMove inventoryMove) {
    InventoryItem item = new InventoryItem();
    item.setSiteCode(inventoryMove.getSiteCode());
    item.setMaterialCode(inventoryMove.getMaterialCode());
    item.setWarehouseCode(inventoryMove.getToWarehouseCode());
    item.setSupplierCode(inventoryMove.getSupplierCode());
    item.setLotNum(inventoryMove.getLotNum());
    item.setStorageLocationCode(inventoryMove.getToLocationCode());
    InventoryItem inventoryItem = inventoryDao.selectInventoryItem(item);
    if (null == inventoryItem) {
      item.setQuantity(inventoryMove.getQuantity());
      item.setCreateUser(inventoryMove.getCreateUser());
      item.setCreateDateTime(new Date());
      item.setModifyUser(inventoryMove.getCreateUser());
      item.setModifyDateTime(new Date());
      // 新增库存明细
      inventoryDao.insertInventoryItem(item);
    } else {
      if (inventoryItem.getQuantity().doubleValue() + inventoryMove.getQuantity().doubleValue() != 0d) {
        inventoryItem.setQuantity(inventoryItem.getQuantity() + inventoryMove.getQuantity());
        inventoryItem.setModifyUser(inventoryMove.getCreateUser());
        inventoryItem.setModifyDateTime(new Date());
        // 更新库存明细
        inventoryDao.updateInventoryItem(inventoryItem);
      } else {
        inventoryDao.deleteInventoryItem(inventoryItem.getId());
      }
    }

    Inventory inventory = inventoryDao.selectInventory(inventoryMove.getSiteCode(), inventoryMove.getMaterialCode(),
        inventoryMove.getToWarehouseCode());
    if (null == inventory) {
      inventory = new Inventory();
      inventory.setSiteCode(inventoryMove.getSiteCode());
      inventory.setWarehouseCode(inventoryMove.getToWarehouseCode());
      inventory.setMaterialCode(inventoryMove.getMaterialCode());
      inventory.setCreateUser(inventoryMove.getCreateUser());
      inventory.setCreateDateTime(new Date());
      inventory.setModifyUser(inventoryMove.getCreateUser());
      inventory.setModifyDateTime(new Date());
      inventory.setQuantity(inventoryMove.getQuantity());
      // 新增库存
      inventoryDao.insertInventory(inventory);
    } else {
      // 更新库存数量
      if (inventory.getQuantity().doubleValue() + inventoryMove.getQuantity().doubleValue() != 0d) {
        inventory.setQuantity(inventory.getQuantity() + inventoryMove.getQuantity());
        inventory.setModifyUser(inventoryMove.getCreateUser());
        inventory.setModifyDateTime(new Date());
        inventoryDao.updateInventory(inventory);
      } else {
        inventoryDao
            .deleteInventory(inventory.getSiteCode(), inventory.getMaterialCode(), inventory.getWarehouseCode());
      }
    }
  }

  @Override
  public double getInventory(Requirement requirement) {
    return inventoryDao.getInventory(requirement);
  }

  @Override
  public List<InventoryItem> getInventoryItemsByItem(InventoryItem inventoryItem) {
    if (inventoryItem == null) {
      return null;
    }
    return inventoryDao.selectInventoryItemsByItem(inventoryItem);
  }

  @Override
  public void productBuckleMaterial(String siteCode, String workUnitCode, String workCenterCode, double quantity,
      String materialCode) {
    //依次从作业单元、工作中心、PFEP查找物料组件对应的线边库、库位
    InventoryItem item = new InventoryItem();
    item.setSiteCode(siteCode);
    item.setMaterialCode(materialCode);
    if (!StringUtils.isBlank(workUnitCode)) {
      WorkUnit workUnit = workUnitService.getWorkUnit(workUnitCode, siteCode);

      if (!StringUtils.isBlank(workUnit.getWarehouseCode())) {
        List<InventoryItem> inventoryItem = checkInventoryItem(workUnit.getWarehouseCode(),
            workUnit.getStorageLocationCode(), item);
        if (inventoryItem != null && inventoryItem.size() > 0) {
          //出库操作
          doInStock(materialCode, quantity, inventoryItem);
          return;
        }
      }
    }
    if (!StringUtils.isBlank(workCenterCode)) {
      WorkCenter workCenter = workCenterService.getWorkCenterByPK(siteCode, workCenterCode);
      if (!StringUtils.isBlank(workCenter.getWarehouseCode())) {
        List<InventoryItem> inventoryItem = checkInventoryItem(workCenter.getWarehouseCode(),
            workCenter.getStorageLocationCode(), item);
        if (inventoryItem != null && inventoryItem.size() > 0) {
          //出库操作
          doInStock(materialCode, quantity, inventoryItem);
          return;
        }
      }
    }
    PFEP pfep = pFEPService.selectPFEP(siteCode, materialCode);
    if (pfep != null && !StringUtils.isBlank(pfep.getWarehouseCode())) {
      List<InventoryItem> inventoryItem = checkInventoryItem(pfep.getWarehouseCode(), pfep.getStorageLocationCode(),
          item);
      if (inventoryItem != null && inventoryItem.size() > 0) {
        //出库操作
        doInStock(materialCode, quantity, inventoryItem);
        return;
      }
    }
  }

  private List<InventoryItem> checkInventoryItem(String warehouseCode, String storageLocationCode, InventoryItem item) {
    item.setWarehouseCode(warehouseCode);
    //是否启用库位
    Warehouse warehouse = warehouseService.getWarehouse(warehouseCode, item.getSiteCode());
    if (warehouse.getLocationManageFlag() == 1) {
      item.setStorageLocationCode(storageLocationCode);
    }
    return inventoryDao.selectInventoryItemsByItem(item);
  }

  /**
   * 依次按照供应商，批次号扣除物料，数量够就只扣一次不够，就全部扣完，继续下个供应商的扣
   */
  private void doInStock(String materialCode, double quantity, List<InventoryItem> inventoryItems) {
    if (quantity <= 0) {
      return;
    }
    InventoryMove inventoryMove = new InventoryMove();
    for (InventoryItem inventoryItem : inventoryItems) {
      inventoryMove.setSiteCode(inventoryItem.getSiteCode());
      inventoryMove.setSupplierCode(inventoryItem.getSupplierCode());
      inventoryMove.setLotNum(inventoryItem.getLotNum());
      inventoryMove.setMaterialCode(materialCode);
      inventoryMove.setFromWarehouseCode(inventoryItem.getWarehouseCode());
      inventoryMove.setFromLocationCode(inventoryItem.getStorageLocationCode());
      inventoryMove.setMoveTypeCode(MmConstant.MOVETYPECODE);
      inventoryMove.setCreateDateTime(new Date());
      inventoryMove.setCreateUser(SecurityContextUtil.getCurrentUserName());
      inventoryMove.setModifyDateTime(new Date());
      inventoryMove.setModifyUser(SecurityContextUtil.getCurrentUserName());
      if (quantity <= inventoryItem.getQuantity().doubleValue()) {
        inventoryMove.setQuantity(quantity);
        this.outStock(inventoryMove, inventoryItem);
        break;
      } else {
        inventoryMove.setQuantity(inventoryItem.getQuantity().doubleValue());
        quantity -= inventoryItem.getQuantity().doubleValue();
        this.outStock(inventoryMove, inventoryItem);
      }
    }
  }
}
